home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archivers / CompDisk / CompSub.c < prev    next >
Text File  |  1996-09-26  |  5KB  |  354 lines

  1. long __regargs    memwrite(char *,long);
  2. void        compexit(void);
  3. long        compinit(void);
  4. long __regargs    compfiles(unsigned char *,long,unsigned char *,long);
  5. long        compress(void);
  6. void __regargs    output(long);
  7. void        cl_block(void);
  8. void        cl_hash(long);
  9.  
  10. #define BITS 12
  11.  
  12. #if BITS == 16
  13. #    define HSIZE    69001 
  14. #endif
  15. #if BITS == 15
  16. #    define HSIZE    35023 
  17. #endif
  18. #if BITS == 14
  19. #    define HSIZE    18013 
  20. #endif
  21. #if BITS == 13
  22. #    define HSIZE    9001 
  23. #endif
  24. #if BITS <= 12
  25. #    define HSIZE    5003 
  26. #endif
  27.  
  28. #define BLOCK_MASK    0x80
  29. #define INIT_BITS    9 
  30. #define htabof(i)    htab[i]
  31. #define codetabof(i)    codetab[i]
  32. #define MAXCODE(n_bits)    ((1 << (n_bits)) - 1)
  33. #define CHECK_GAP    10000
  34. #define FIRST        257 
  35. #define CLEAR        256 
  36.  
  37. #define myfgetc()    (reallyread++ >= watermark) ? EOF : *sect++
  38. #define absmin(a,b)    ((a > b) ? b : a)
  39.  
  40. long n_bits,maxcode,*htab,hsize,free_ent,clear_flg,ratio,checkpoint,offset,in_count,bytes_out,reallywritten,watermark,buffsize,reallyread;
  41.  
  42. unsigned char *buffstart,*sect;
  43. unsigned short *codetab;
  44.  
  45. char buf[BITS];
  46.  
  47. const unsigned char lmask[9] = {0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00};
  48. const unsigned char rmask[9] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};
  49.  
  50. long __regargs
  51. memwrite(mem,size)
  52. register char *mem;
  53. register long size;
  54. {
  55.     register long byteswritten = 0;
  56.  
  57.     while(size-- > 0)
  58.     {
  59.         if(reallywritten++ < buffsize)
  60.         {
  61.             *buffstart++ = *mem++;
  62.             byteswritten++;
  63.         }
  64.         else
  65.             return(byteswritten);
  66.     }
  67.  
  68.     return(byteswritten);
  69. }
  70.  
  71. void
  72. compexit()
  73. {
  74.     if(htab)
  75.         FreeMem(htab,HSIZE * sizeof(long));
  76.  
  77.     if(codetab)
  78.         FreeMem(codetab,HSIZE * sizeof(unsigned short));
  79.  
  80.     htab = NULL;
  81.     codetab = NULL;
  82. }
  83.  
  84. long
  85. compinit()
  86. {
  87.     if(!(htab = (long *)AllocMem(HSIZE * sizeof(long),0)))
  88.         return(FALSE);
  89.  
  90.     if(!(codetab = (unsigned short *)AllocMem(HSIZE * sizeof(unsigned short),0)))
  91.     {
  92.         FreeMem(htab,HSIZE * sizeof(long));
  93.  
  94.         htab = NULL;
  95.  
  96.         return(FALSE);
  97.     }
  98.  
  99.     return(TRUE);
  100. }
  101.  
  102. void __regargs
  103. output(code)
  104. long code;
  105. {
  106.     long r_off = offset, bits = n_bits;
  107.     register char *bp = buf;
  108.  
  109.     if(code >= 0)
  110.     {
  111.         bp += (r_off >> 3);
  112.         r_off &= 7;
  113.  
  114.         *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
  115.         bp++;
  116.  
  117.         bits -= (8 - r_off);
  118.         code >>= 8 - r_off;
  119.  
  120.         if(bits >= 8)
  121.         {
  122.             *bp++ = code;
  123.             code >>= 8;
  124.             bits -= 8;
  125.         }
  126.  
  127.         if(bits)
  128.             *bp = code;
  129.  
  130.         offset += n_bits;
  131.  
  132.         if(offset == (n_bits << 3))
  133.         {
  134.             bp = buf;
  135.             bits = n_bits;
  136.             bytes_out += bits;
  137.  
  138.             do
  139.             {
  140.                 if(reallywritten++ < buffsize)
  141.                     *buffstart++ = *bp++;
  142.             }
  143.             while(--bits);
  144.  
  145.             offset = 0;
  146.         }
  147.  
  148.         if(free_ent > maxcode || (clear_flg > 0))
  149.         {
  150.             if(offset > 0)
  151.             {
  152.                 memwrite(buf,n_bits);
  153.                 bytes_out += n_bits;
  154.             }
  155.  
  156.             offset = 0;
  157.  
  158.             if(clear_flg)
  159.             {
  160.                 maxcode = MAXCODE(n_bits = INIT_BITS);
  161.                 clear_flg = 0;
  162.             }
  163.             else
  164.             {
  165.                 n_bits++;
  166.  
  167.                 if(n_bits == BITS)
  168.                     maxcode = (1 << BITS);
  169.                 else
  170.                     maxcode = MAXCODE(n_bits);
  171.             }
  172.         }
  173.     }
  174.     else
  175.     {
  176.         if(offset > 0)
  177.             memwrite(buf,(offset + 7) / 8);
  178.  
  179.         bytes_out += (offset + 7) / 8;
  180.         offset = 0;
  181.     }
  182. }
  183.  
  184. void
  185. cl_block()
  186.     register long rat;
  187.  
  188.     checkpoint = in_count + CHECK_GAP;
  189.  
  190.     if(in_count > 0x007FFFFF)
  191.     {
  192.         rat = bytes_out >> 8;
  193.  
  194.         if(rat == 0)
  195.             rat = 0x7FFFFFFF;
  196.         else
  197.             rat = in_count /rat;
  198.     }
  199.     else
  200.         rat = (in_count << 8) / bytes_out; 
  201.  
  202.     if(rat > ratio)
  203.         ratio = rat;
  204.     else
  205.     {
  206.         ratio = 0;
  207.  
  208.         cl_hash((long)hsize);
  209.  
  210.         free_ent = FIRST;
  211.         clear_flg = 1;
  212.  
  213.         output((long)CLEAR);
  214.     }
  215. }
  216.  
  217. void
  218. cl_hash(hashsize) 
  219. long hashsize;
  220. {
  221.     register long *htab_p = &htab[hashsize],i;
  222.     register unsigned short j;
  223.  
  224.     i = hashsize - 16;
  225.  
  226.     do
  227.     {
  228.         for(j = 16 ; j > 0 ; j--)
  229.             *(htab_p - j) = -1;
  230.  
  231.         htab_p -= 16;
  232.     }
  233.     while((i -= 16) >= 0);
  234.  
  235.     for(i += 16 ; i > 0 ; i--)
  236.         *--htab_p = -1;
  237. }
  238.  
  239. long __regargs
  240. compfiles(from,sectsize,to,maxsize)
  241. unsigned char *from,*to;
  242. long sectsize,maxsize;
  243. {
  244.     sect        = from;
  245.     watermark    = sectsize;
  246.     buffstart    = to;
  247.     buffsize    = maxsize;
  248.     reallywritten    = 0;
  249.     reallyread    = 0;
  250.  
  251.     hsize        = HSIZE;
  252.     free_ent    = 0;
  253.     clear_flg    = 0;
  254.     ratio        = 0;
  255.     checkpoint    = CHECK_GAP;
  256.     in_count    = 1; 
  257.  
  258.     if(sectsize < (1 << 12))
  259.         hsize = absmin(5003, HSIZE);
  260.     else if(sectsize < (1 << 13))
  261.         hsize = absmin(9001, HSIZE);
  262.     else if(sectsize < (1 << 14))
  263.         hsize = absmin(18013, HSIZE);
  264.     else if(sectsize < (1 << 15))
  265.         hsize = absmin(35023, HSIZE);
  266.     else if(sectsize < 47000)
  267.         hsize = absmin(50021, HSIZE);
  268.  
  269.     compress();
  270.  
  271.     return(reallywritten);
  272. }
  273.  
  274. long
  275. compress()
  276. {
  277.     long fcode,i = 0,c,ent,disp,hsize_reg,hshift = 0;
  278.  
  279.     offset        = 0;
  280.     bytes_out    = 3; 
  281.     clear_flg    = 0;
  282.     ratio        = 0;
  283.     in_count    = 1;
  284.  
  285.     checkpoint = CHECK_GAP;
  286.     maxcode = MAXCODE(n_bits = INIT_BITS);
  287.  
  288.     free_ent = ((BLOCK_MASK) ? FIRST : 256);
  289.  
  290.     ent = myfgetc();
  291.  
  292.     for(fcode = (long)hsize ; fcode < 65536L ; fcode *= 2L)
  293.         hshift++;
  294.  
  295.     hshift = 8 - hshift; 
  296.     hsize_reg = hsize;
  297.  
  298.     cl_hash((long)hsize_reg); 
  299.  
  300.     while((c = myfgetc()) != EOF)
  301.     {
  302.         in_count++;
  303.  
  304.         fcode = (long)(((long) c << BITS) + ent);
  305.  
  306.         i = ((c << hshift) ^ ent); 
  307.  
  308.         if(htabof(i) == fcode)
  309.         {
  310.             ent = codetabof(i);
  311.             continue;
  312.         }
  313.         else
  314.             if((long)htabof(i) < 0) 
  315.                 goto nomatch;
  316.  
  317.         disp = hsize_reg - i; 
  318.  
  319.         if(i == 0)
  320.             disp = 1;
  321.  
  322. probe:        if((i -= disp) < 0)
  323.             i += hsize_reg;
  324.  
  325.         if(htabof(i) == fcode)
  326.         {
  327.             ent = codetabof(i);
  328.             continue;
  329.         }
  330.  
  331.         if((long)htabof(i) > 0)
  332.             goto probe;
  333.  
  334. nomatch:    output((long)ent);
  335.  
  336.         ent = c;
  337.  
  338.         if(free_ent < (1 << BITS))
  339.         {
  340.             codetabof(i) = free_ent++; 
  341.             htabof(i) = fcode;
  342.         }
  343.         else
  344.             if((long)in_count >= checkpoint && BLOCK_MASK)
  345.                 cl_block();
  346.     }
  347.  
  348.     output((long)ent);
  349.     output((long)-1);
  350.  
  351.     return(bytes_out);
  352. }
  353.